package com.tansun.easycare.rule.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.tansun.easycare.core.utils.IdGen;
import com.tansun.easycare.rule.common.BomCreator;
import com.tansun.easycare.rule.common.CommonEnum;
import com.tansun.easycare.rule.common.DateCheckUtils;
import com.tansun.easycare.rule.common.model.BaseItem;
import com.tansun.easycare.rule.common.model.Bom;
import com.tansun.easycare.rule.common.model.BomField;
import com.tansun.easycare.rule.common.model.Domain;
import com.tansun.easycare.rule.common.model.DomainItem;
import com.tansun.easycare.rule.common.symbol.Symbol;
import com.tansun.easycare.rule.common.symbol.SymbolCreator;
import com.tansun.easycare.rule.decisiontree.entity.DecisionTreeEntity;
import com.tansun.easycare.rule.decisiontree.model.DecisionSubNode;
import com.tansun.easycare.rule.decisiontree.model.DecisionSubNodeItem;
import com.tansun.easycare.rule.exception.BizException;
import com.tansun.easycare.rule.policytree.model.PolicyTreeItem;
import com.tansun.easycare.rule.policytree.model.PolicyTreeKey;
import com.tansun.easycare.rule.policytree.model.PolicyTreeModel;
import com.tansun.easycare.rule.policytree.model.PolicyTreeScene;
import com.tansun.easycare.rule.rulegroup.model.RuleExpessVO;
import com.tansun.easycare.rule.rulegroup.model.RuleSetExpressVO;
import com.tansun.easycare.rule.rulemange.entity.RuleManage;
import com.tansun.easycare.rule.scoremodel.entity.RuleScoreInfo;
import com.tansun.easycare.rule.scoremodel.model.ScoreEntity;
import com.tansun.easycare.rule.scoremodel.model.ScoreItem;
import com.tansun.easycare.rule.table.exclusions.entity.ExclusionsBO;
import com.tansun.easycare.rule.table.exclusions.entity.ExclusionsVo;
import com.tansun.rule.utils.LoggerManager;
import com.tansun.rule.utils.StringUtils;

public class ExcelUtils {
    //中文参数名称Key
    private Map<String, BomField> paramZnMap = new HashMap<String, BomField>();
    //英文文参数名称Key
    private Map<String, BomField> paramEnMap = new HashMap<String, BomField>();
    //记得有重复名字的对象
    private Map<String, String> repeatedName = new HashMap<String, String>();
    //所属类名前缀
    private Map<String, BomField> parentMap = new HashMap<String, BomField>();
    private Map<String,Symbol> symbolMap = new HashMap<>();
    private Map<String, Domain> attrMap;
    //合并单元格
    private List<CellRangeAddress> mergedRegionList = new ArrayList<CellRangeAddress>();
    //错误累积数
    private int errCount = 0;
    //错误信息
    private StringBuilder errMsg = new StringBuilder();

    //决策树节点
    private List<DecisionSubNode> nodeList;

    //决策树输出变量参数
    private List<BomField> outVarList;

    //输出变量起始列
    private int outColIndex;

    // Map<rowIndex, Map<colIndex, mergeCellColIndex>>
    private Map<Integer, Map<Integer, Integer>> mergeCellMap = new HashMap<Integer, Map<Integer, Integer>>();

    public ExcelUtils(Map<String, Domain> attrMap, Map<String, Bom> metaMap) {
        getParam(metaMap);
        getSymbolMap();
        this.attrMap = attrMap;
    }

    public Workbook readExcelData(MultipartFile file) throws Exception {
        Workbook workbook = null;
        try {
            if (file.getOriginalFilename().toLowerCase().endsWith("xlsx")) {
                workbook = new XSSFWorkbook(file.getInputStream());
            } else if (file.getOriginalFilename().toLowerCase().endsWith("xls")) {
                workbook = new HSSFWorkbook(file.getInputStream());
            } else {
                throw new IllegalStateException("文件格式有误");
            }
        } catch (IOException e) {
            LoggerManager.error(e.getMessage(), e, this.getClass());
        } finally {
            if (file != null && file.getInputStream() != null)
                file.getInputStream().close();
        }
        return workbook;
    }

    /**
     * 解析上传的评分模型文件
     */
    public ScoreEntity parseScoreModel(MultipartFile file, String projectCode,String rankRelationId) throws Exception {
        ScoreEntity scoreEntity = new ScoreEntity();
        RuleManage model = new RuleManage();
        model.setRankRelationId(rankRelationId);
        String[] arr = file.getOriginalFilename().split("_");
        if (arr.length == 3) {
            model.setCode(arr[0]);
            model.setVersion(arr[1]);
        }
        model.setProjectCode(projectCode);
        Workbook workbook = readExcelData(file);
        ArrayList<ScoreItem> scoreList = new ArrayList<ScoreItem>();
        Sheet sheet = workbook.getSheetAt(0);
        getScoreModeDataFirst(sheet, model,scoreEntity,scoreList);
        if(workbook.getNumberOfSheets() > 1) {
	        sheet = workbook.getSheetAt(1);
	        getScoreModeDataSecond(sheet, model, scoreEntity,scoreList);
        }
        scoreEntity.setTreeList(scoreList);
        markError("0");
        return scoreEntity;
    }
    
    /**
     * 获取评分模型分段细分的信息
     * @param sheet
     * @param model
     * @param scoreEntity
     * @param scoreList
     */
    private void getScoreModeDataFirst(Sheet sheet,RuleManage model,ScoreEntity scoreEntity,ArrayList<ScoreItem> scoreList) {
        int rowNum = sheet.getLastRowNum();
        Row row = sheet.getRow(0);
        int parentTreeId = 0;
        int treeId = 0;
        for (int x = 0; x <= rowNum; x++) {
            row = sheet.getRow(x);
            if (row.getCell(0) != null && row.getCell(0).toString().indexOf("{end}") > -1) {
                break;
            }
            if (x == 0) {//正文内容应该从第三行开始,第一行为表头的标题
                if (row.getCell(0) == null)
                    throw new IllegalStateException("请填写评分模型名称");
                model.setName(row.getCell(0).toString());
                scoreEntity.setScoreModel(model);
                continue;
            } else if (x != 1) {
                String paramName = row.getCell(0) == null ? null : row.getCell(0).toString();
                if (!StringUtils.isEmpty(paramName)) {
                    BomField param = paramZnMap.get(paramName);
                    if (param == null) {
                        throw new IllegalStateException("第" + (x + 1) + "行的参数\"" + paramName + "\"不存在，请确定数据模型中存在此参数。");
                    }
                    ScoreItem item = new ScoreItem();
                    item.setContentType(CommonEnum.ScoreModelType.scoreDetail.toString());
                    item.initModel(param);
                    String scoreParam = row.getCell(1).toString();
                    if (param.getName().equals("initialScore"))//初始分数取值
                        scoreParam = row.getCell(1).toString();
                    if (!isNumber(scoreParam))
                        throw new IllegalStateException("第" + (x + 1) + "行，" + item.getNamecn() + "的参数值请输入数字");
                    item.setScoreParam(Double.parseDouble(scoreParam));
                    item.setTreeId("3-" + (++parentTreeId));
                    scoreList.add(item);
                }
                try {
                    ScoreItem item = scoreList.get(scoreList.size() - 1);
                    if (item.getNameen().equals("initialScore")) {
                        continue;
                    }
                    RuleScoreInfo child = new RuleScoreInfo();
                    String scoreSection = row.getCell(2).toString();
                    if (StringUtils.isEmpty(scoreSection)) {
                        throw new IllegalStateException(item.getNamecn() + "请输入评分分段数据");
                    }
                    scoreSection = scoreSection.trim();
                    if (item.getDataType().equals("String") && !StringUtils.isEmpty(item.getDomain())) {
                    	//判断 为枚举项
                        if ("其他".equals(scoreSection) || "其它".equals(scoreSection)) {

                        } else {
                            if ( scoreSection.endsWith("除外!") || scoreSection.endsWith("除外！")) {
                                child.setSymbol("0");
                                scoreSection = scoreSection.replace("除外!", "").replace("除外！", "").trim().substring(1);
                                scoreSection = scoreSection.substring(0,scoreSection.length()-1);
                            } else {
                                child.setSymbol("1");
                            }
                        }
                    }

                    String[] controlVals = parseParam(scoreSection, item);
                    child.setContrastVals(Arrays.toString(controlVals));
                    child.setLabel(getScoreLabel(item, child, scoreSection));
                    if ("其他".equals(scoreSection) || "其它".equals(scoreSection)) {
                        child.setIsOther("1");
                    } else {
                        if ("String".equals(item.getDataType()) && (item.getDomain()==null || item.getDomain().length() == 0)) {
                            if (controlVals != null && controlVals.length == 2) {
                                child.setSymbol(controlVals[0]);
                                child.setContrastVals(controlVals[1]);
                            }
                        } else if (controlVals != null && controlVals.length == 4) {
                            child.setLowerOpt(controlVals[0]);
                            child.setLowerVal(controlVals[1]);
                            child.setUpperOpt(controlVals[2]);
                            child.setUpperVal(controlVals[3]);
                        } else if ("Boolean".equals(item.getDataType())) {
                            child.setContrastVals(controlVals[0]);
                        }
                    }
                    child.setScopeDesc(row.getCell(3) == null ? "" : row.getCell(3).toString());
                    String scoreVal = row.getCell(4) == null ? "" : row.getCell(4).toString();
                    if (isNumber(scoreVal)) {
                    	//分段
                    	child.setSectionType("0");
                    	child.setScoreVal(Double.parseDouble(scoreVal));
                    }else {
                    	// 线性
                    	child.setSectionType("2");
                    	child.setFormulaLabel(scoreVal);
                    	String formual = sectionFormulaEdit(scoreVal);
                    	child.setFormula(formual);
                    }
                    child.setTreeId(item.getTreeId() + "-" + (++treeId));
                    child.setSeq(treeId);
                    item.getList().add(child);
                } catch (IllegalStateException e) {
                    markError("第" + (x + 1) + "行，" + e.getMessage());
                }
            }
            
        }
    }
    private void getScoreModeDataSecond(Sheet sheet,RuleManage model,ScoreEntity scoreEntity,ArrayList<ScoreItem> scoreList) {
        BomField sectionParam = new BomField();
        String formualLabel =  null;
        String formual =  null;
    	for (int x = 2; x <= sheet.getLastRowNum(); x++) {
    		Row row = sheet.getRow(x);
            String paramName = row.getCell(0).toString();
            sectionParam = paramZnMap.get(paramName);
            if (sectionParam == null) {
                throw new IllegalStateException("第" + (x + 1) + "行的参数\"" + paramName + "\"不存在，请确定数据模型中存在此参数。");
            }
            ScoreItem item = new ScoreItem();
            item.initModel(sectionParam);
            
            formualLabel = row.getCell(2).toString();
            if (StringUtils.isEmpty(formualLabel) ) {
                throw new IllegalStateException(item.getNamecn() + "汇总公式描述不存在!");
            }
            if(x == 2) {
            	item.setContentType(CommonEnum.ScoreModelType.scoreSummary.toString());
                //formual = summaryFormulaEdit(formualLabel);
            	formual = sectionFormulaEdit(formualLabel);
            }else {
            	item.setContentType(CommonEnum.ScoreModelType.scoreSection.toString());
            	formual = sectionFormulaEdit(formualLabel);
            }
            item.setFormula(formual);
            item.setFormulaLabel(formualLabel);
            
            scoreList.add(item);
        }
    }

    /**
     * 公式转化
     *  "初始评分 + ce33.shu1*1 + (shujusadasdsad.心情*1 - shuju2.整数2)/1 + shuju2.整数1*1"
     *  #{InitialScore.initialScore} + #{ce33.shu1}*1 + #{shuju1.xinq}*1 + #{shuju2.one_2}*1 + #{shuju2.one_1}*1
     * @param formualLabel
     * @return
     */
    private String summaryFormulaEdit(String formualLabel) {
		String[] formualArr = formualLabel.split("\\+|\\-|\\*|\\/|\\(|\\)|\\%");
		BomField sectionParam = new BomField();
		for(String each:formualArr) {
			each = each.trim();
			if(StringUtils.isNotEmpty(each) && !isNumeric(each) ) {
				if("初始评分".equals(each)) {
					formualLabel = formualLabel.replace("初始评分", "#{InitialScore.initialScore}");
				}else if(each.contains(".")){
					String[] classParam = each.split("\\.");
					sectionParam = paramZnMap.get(classParam[1]);
					formualLabel = formualLabel.replace(each, "#{"+sectionParam.getClassName() + "." + sectionParam.getName() +"}"); 
				}else {
					sectionParam = paramZnMap.get(each);
					formualLabel = formualLabel.replace(each, "#{"+sectionParam.getClassName() + "." + sectionParam.getName() +"}");
				}
			}
		}
    	return formualLabel;
    }
    /**
     * 公式转化
     *  shuju2.整数3 * 999
     *  [{"action":[{"label":"shuju2","name":"shuju2","type":"bom"},{"id":"efc4bf54de954b25bd689caef5b9e766","label":"整数3","name":"zhusu3","dataType":"Long","collection":"","isfirst":true,"type":"field"},{"label":" * ","name":"times","drlSymbol":" * ","type":"sym"},{"id":"efc4bf54de954b25bd689caef5b9e766","name":"constant","value":"999","dataType":"Long","type":"constant","domainInfo":{},"isReplace":""},{"label":";","name":";","type":"sym"}]}]
     * @param formualLabel
     * @return
     */
    private String sectionFormulaEdit(String formualLabel) {
    	RuleSetExpressVO ruleSetExpressVO = new RuleSetExpressVO();
    	List<RuleExpessVO> action = new ArrayList<>(); 
		
        String regex = ".*?([\\+\\-\\*\\/\\(\\)\\%]).*?";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(formualLabel);
        int end = 0;
        String group = null;
        String symbol = null;
    	BomField sectionParam = null;
        while (matcher.find()) {
        	group = matcher.group();
        	symbol = matcher.group(1);
        	group = group.replace(symbol, "").trim();
        	sectionParam = parseString(group,symbol.trim(),action,sectionParam);
        	end = matcher.end();
        }
        if(end != 0 ) {
        	group = formualLabel.substring(end);
        	sectionParam = parseString(group.trim(),"",action,sectionParam);
        }
		RuleExpessVO ruleExpessVO = new RuleExpessVO();
		ruleExpessVO.setType("sym");
		ruleExpessVO.setLabel(";");
		ruleExpessVO.setName(";");
		action.add(ruleExpessVO);
        ruleSetExpressVO.setAction(action);
    	return JSON.toJSONString(new ArrayList<RuleSetExpressVO>() {{add(ruleSetExpressVO);}});
    }
    
    private BomField parseString(String group,String symbol,List<RuleExpessVO> action, BomField sectionParam) {
    	if(StringUtils.isNotEmpty(group)) {
			if(isNumeric(group) ) {
				RuleExpessVO ruleExpessVO = new RuleExpessVO();
                ruleExpessVO.setType("constant");
                if(sectionParam == null) {
                	ruleExpessVO.setDataType(group.contains(".")?"Double":"Long");
                }else {
                	ruleExpessVO.setDataType(sectionParam.getDataType());
                }
                ruleExpessVO.setValue(group);
                ruleExpessVO.setName("constant");
                action.add(ruleExpessVO);
			}else {
				String[] classParam = group.split("\\.");
				if("初始评分".equals(classParam[0])) {
					classParam = new String[] {"本评分模型","初始评分"};
				}
				sectionParam = paramZnMap.get(classParam[1]);
				RuleExpessVO ruleExpessVOClass = new RuleExpessVO();
				ruleExpessVOClass.setType("bom");
				ruleExpessVOClass.setLabel(classParam[0]);
				ruleExpessVOClass.setName(sectionParam.getClassName());
				action.add(ruleExpessVOClass);
				
				RuleExpessVO ruleDataParam = new RuleExpessVO();
	            ruleDataParam.setType("field");
	            ruleDataParam.setLabel(classParam[1]);
	            ruleDataParam.setName(sectionParam.getName());
	            ruleDataParam.setDataType(sectionParam.getDataType());
	            action.add(ruleDataParam);
			}
		}
    	if(StringUtils.isNotEmpty(symbol)){
    		Symbol symbolObj = symbolMap.get(symbol);
			RuleExpessVO ruleExpessVO = new RuleExpessVO();
			ruleExpessVO.setType("sym");
			ruleExpessVO.setLabel(symbolObj.getLabel());
			ruleExpessVO.setName(symbolObj.getName());
			ruleExpessVO.setDrlSymbol(symbolObj.getDrlSymbol());
			action.add(ruleExpessVO);
        }
    	return sectionParam;
    }
    
    private static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]+[\\.]?[\\d]*$");  
        return pattern.matcher(str).matches();  
    }
    
    private String getScoreLabel(ScoreItem item, RuleScoreInfo child, String scoreSection) {
        if ("其他".equals(scoreSection)) {
            return scoreSection;
        }
        String retStr = "";
        if ("String".equalsIgnoreCase(item.getDataType())) {
            if (!StringUtils.isEmpty(item.getDomain())) {//枚举型
                retStr = child.getSymbol().equals("1") ? scoreSection : "(" + scoreSection + ")除外";
            } else {//字符型
                // retStr = scoreSection;
                //scoreSection = scoreSection.substring(1);
                if (scoreSection.startsWith("==")) {
                    retStr = "等于" + scoreSection.substring(3);
                } else if (scoreSection.startsWith("!=")) {
                    retStr = "不等于" + scoreSection.substring(3);
                } else if (scoreSection.startsWith("contains")) {
                    retStr = "包含" + scoreSection.substring("contains".length() + 1);
                } else if (scoreSection.startsWith("not contains")) {
                    retStr = "不包含" + scoreSection.substring("not contains".length() + 1);
                } else if (scoreSection.startsWith("startsWith")) {
                    retStr = "以" + scoreSection.substring("startsWith".length() + 1) + "开头";
                } else if (scoreSection.startsWith("endsWith")) {
                    retStr = "以" + scoreSection.substring("endsWith".length() + 1) + "结尾";
                }
                return retStr;

            }
        } else if ("Boolean".equalsIgnoreCase(item.getDataType())) {
            retStr = scoreSection;
        } else {
            String downSymbol = null;
            String upSysbol = null;
            String[] doubleArr = null;//区间值
            int idd = scoreSection.indexOf("@");//数值类型的输入变量当输入值的符号为:"=="时
            int idn = scoreSection.indexOf("#");//数值类型的输入变量当输入值的符号为:"!="时
            if(idd > -1 && idn == -1) {
                downSymbol = "==";
                upSysbol = "";
                doubleArr = new String[]{scoreSection.replace("@", "")};
            }else if(idd == -1 && idn > -1){
                downSymbol = "!=";
                upSysbol = "";
                doubleArr = new String[]{scoreSection.replace("#", "")};
            }else {
                downSymbol = scoreSection.substring(0, 1);
                upSysbol = scoreSection.substring(scoreSection.length() - 1);
                downSymbol = downSymbol.equals("[") ? ">=" : ">";
                upSysbol = upSysbol.equals("]") ? "<=" : "<";
                doubleArr = scoreSection.substring(1, scoreSection.length() - 1).split(",");
            }
            if (doubleArr.length == 1) {
                retStr = "x " + downSymbol + " " + doubleArr[0];
            } else if (doubleArr.length == 2) {
            	if(StringUtils.isEmpty(doubleArr[0])) {
            		retStr = "x " + upSysbol + " " + doubleArr[1];
            	}else if(StringUtils.isEmpty(doubleArr[1])) {
            		retStr = "x " + downSymbol + " " + doubleArr[0];
            	}else {
            		retStr = "x " + downSymbol + " " + doubleArr[0] + " && x " + upSysbol + " " + doubleArr[1];
            	}
                
            }
        }
        return retStr;
    }

    private String[] parseParam(String controlVal, ScoreItem base) throws IllegalStateException {
        List<String> sList = new ArrayList();
        sList.add("!=");
        sList.add("==");
        //not contains必须在contains之前比较
        sList.add("not contains");
        sList.add("contains");
        sList.add("startsWith");
        sList.add("endsWith");
        List<String> paramList = new ArrayList<String>();
        if ("String".equals(base.getDataType())) {
            if (!StringUtils.isEmpty(base.getDomain())) {//枚举类型
                Domain domain = getDomain(base.getDomain());
                //controlVal = controlVal.replace("[", "").replace("]", "").replaceAll("\"", "");
                String[] vals = controlVal.split("&");
                int valCount = 0;
                for (int i=0;i<vals.length;i++) {
                	String str = vals[i].trim();
                	if(StringUtils.isNotEmpty(str)) {
                        //domain:"333" str:["333"]
                        for (DomainItem item : domain.getDomainItems()) {
                            if (item.getLabel().equals(str) || item.getValue().equals(str)) {
                                // paramList.add("\""+item.getValue()+"\"");
                                paramList.add("\"" + item.getValue() + "\"");
                                valCount++;
                                break;
                            }
                        }
                	}

                }
                if (paramList.size() != valCount) {
                    if ("其他".equals(controlVal) || "其它".equals(controlVal)) {
                        return new String[]{controlVal};
                    } else {
                        throw new IllegalStateException(base.getNamecn() + "的参数值存在与数据模型不匹配的值，请检查");
                    }
                }
            } else {//字符类型
                if (controlVal != null) {
                    List<String> sList1 = new ArrayList();
                    sList1.add("不等于");
                    sList1.add("等于");
                    //not contains必须在contains之前比较
                    sList1.add("不包含");
                    sList1.add("包含");
                    sList1.add("以xxx开头");
                    sList1.add("以xxx结尾");
                    for (int i=0;i<sList.size();i++) {
                        String eStr1=sList1.get(i);
                        String eStr=sList.get(i);
                        if(controlVal.indexOf(eStr1)>-1){
                            controlVal=controlVal.replaceAll(eStr1,eStr);
                        }
                        int idx = controlVal.indexOf(eStr);
                        if (idx > -1) {
                            paramList.add(controlVal.substring(idx, eStr.length()).trim());
                            paramList.add(controlVal.substring(eStr.length()).trim());
                            break;
                        }
                    }
                }
            }
        } else if (base.getDataType().equals("Date") || base.getDataType().equals("Double") || base.getDataType().equals("Long") || base.getDataType().equals("BigDecimal")  || base.getDataType().equals("BigInteger")) {
            if ("其他".equals(controlVal)) {
                return new String[]{controlVal};
            }
            String downSymbol = null;//下限
            String upSysbol = null;//上限
            String[] doubleArr = null;//区间值
            int idd = controlVal.indexOf("@");//数值类型的输入变量当输入值的符号为:"=="时
            int idn = controlVal.indexOf("#");//数值类型的输入变量当输入值的符号为:"!="时
            
            if(idd > -1 && idn == -1) {
                downSymbol = "==";
                upSysbol = "";
                doubleArr = new String[]{controlVal.replace("@", "")};
            }else if(idd == -1 && idn > -1){
                downSymbol = "!=";
                upSysbol = "";
                doubleArr = new String[]{controlVal.replace("#", "")};
            }else {
                if (!(controlVal.indexOf("[") == 0 || controlVal.indexOf("(") == 0)
                        || !(controlVal.indexOf("]") == (controlVal.length() - 1) || controlVal.indexOf(")") == (controlVal.length() - 1))) {
                    throw new IllegalStateException(base.getNamecn() + "的参数值请使用“[、(、)、]”符号好产生一个区间值");
                }
                downSymbol = controlVal.substring(0, 1);
                upSysbol = controlVal.substring(controlVal.length() - 1);
                if (controlVal.indexOf(",") > -1) {
                    downSymbol = downSymbol.equals("[") ? ">=" : ">";
                    upSysbol = upSysbol.equals("]") ? "<=" : "<";
                } else {
                    downSymbol = "==";
                    upSysbol = "";
                }
                doubleArr = controlVal.substring(1, controlVal.length() - 1).split(",");
                if (doubleArr.length == 0) {
                    throw new IllegalStateException(base.getNamecn() + "的参数值请输入在" + base.getDomain() + "区间的值");
                }
            }
            paramList.add(downSymbol);
            String[] limitArr = null;
            if (!StringUtils.isEmpty(base.getDomain())) {
                limitArr = base.getDomain().substring(1, base.getDomain().length() - 1).split(",");
            }

            for (int i = 0; i < doubleArr.length; i++) {
                String str = doubleArr[i];
                if (!"".equals(str)) {
                    if (!base.getDataType().equals("Date")) {
                        if (!isNumber(str))
                            throw new IllegalStateException(base.getNamecn() + "的参数值请输入数字");
                        if (limitArr != null && !validateSectionVal(str, limitArr, base.getDataType())) {
                            throw new IllegalStateException(base.getNamecn() + "的参数值请输入在" + base.getDomain() + "区间的值");
                        }
                    } else {
                        if (!DateCheckUtils.dateFormatCheck(str))
                            throw new IllegalStateException(base.getNamecn() + "的参数值请输入日期格式");
                        if (limitArr != null && !validateSectionVal(str, limitArr, base.getDataType())) {
                            throw new IllegalStateException(base.getNamecn() + "的参数值请输入在" + base.getDomain() + "区间的值");
                        }
                    }
                }
                paramList.add(str.trim());
                if (i == 0) {
                    paramList.add(upSysbol);
                }
            }

            if (doubleArr.length == 1) {
                paramList.add("");
                paramList.set(2, "");
            }else {
            	if(StringUtils.isEmpty(paramList.get(1))) {
            		paramList.set(0, "");
            	}
            	if(StringUtils.isEmpty(paramList.get(3))) {
            		paramList.set(2, "");
            	}
            }
        } else if ("Boolean".equals(base.getDataType())) {
            paramList.add(controlVal.equals("是") ? "1" : "0");
        }
        String[] retArr = new String[paramList.size()];
        paramList.toArray(retArr);
        return retArr;
    }

    private String validateControlValue(PolicyTreeScene scene, String controlVal) {
        String value = "";
        String dataType = scene.getDataType();
        if (dataType.equals("String")) {
            if (StringUtils.isEmpty(scene.getDomain())) {
                value = controlVal.equals("有") ? "1" : "0";
                return value;
            } else {
                return convertDomain(scene.getDomain(), controlVal);
            }
        }
        return controlVal;
    }


    public String validateValue(BaseItem base, String controlVal, String type, boolean isTree) {
        String values = "";
        if (type.equals("in")) {
            if (base.getDataType().equals("String")) {
                if (!StringUtils.isEmpty(base.getDomain())) {
                    Domain domain = getDomain(base.getDomain());
                    if (isTree) {
                        controlVal = controlVal.substring(1, controlVal.length() - 1);
                    }
                    String[] vals = controlVal.split(",");
                    values = "[";
                    int count = 0;
                    for (DomainItem item : domain.getDomainItems()) {
                        for (String str : vals) {
                            if (item.getLabel().equals(str)) {
                                values += "\"" + item.getValue() + "\",";
                                count++;
                            }
                        }
                    }
                    values = values.substring(0, values.length() - 1) + "]";
                    if (count == vals.length) {
                        return values;
                    } else {
                        throw new IllegalStateException(controlVal + "：找不到对应的枚举项");
                    }
                } else {
                    values = controlVal;
                    return values;
                }
            } else if (base.getDataType().equals("Double") || base.getDataType().equals("Long")) {
                if (isTree) {
                    if (!isNumber(controlVal))
                        throw new IllegalStateException(base.getNameCN() + "的参数表达式值请输入数字");
                    return controlVal;
                }
                if (!(controlVal.indexOf("[") != 0 || controlVal.indexOf("(") != 0)
                        || !(controlVal.indexOf("]") != (controlVal.length() - 1) || controlVal.indexOf(")") != (controlVal.length() - 1))
                        || controlVal.indexOf(",") < 0) {
                    throw new IllegalStateException(base.getNameCN() + "的参数值请使用“[、(、)、]”符号好产生一个区间值");
                }
                String[] doubleArr = controlVal.substring(1, controlVal.length() - 1).split(",|，");
                String[] limitArr = null;
                if (!StringUtils.isEmpty(base.getDomain())) {
                    limitArr = base.getDomain().substring(1, base.getDomain().length() - 1).split(",");
                }
                for (String str : doubleArr) {
                    if (!isNumber(str))
                        throw new IllegalStateException(base.getNameCN() + "的参数值请输入数字");
                    if (limitArr != null && !StringUtils.isEmpty(base.getDomain()) && !validateSectionVal(str, limitArr, base.getDataType())) {
                        throw new IllegalStateException(base.getNameCN() + "的参数值请输入在" + base.getDomain() + "区间的值");
                    }
                }
                String retStr = controlVal.substring(0, 1) + controlVal.substring(1, controlVal.length() - 1) + controlVal.substring(controlVal.length() - 1);
                return retStr;
            } else if (base.getDataType().equals("Date")) {
                if (isTree) {
                    return controlVal;
                }
                if (!(controlVal.indexOf("[") != 0 || controlVal.indexOf("(") != 0)
                        || !(controlVal.indexOf("]") != (controlVal.length() - 1) || controlVal.indexOf(")") != (controlVal.length() - 1))
                        || controlVal.indexOf(",") < 0) {
                    throw new IllegalStateException(base.getNameCN() + "的参数值请使用“[、(、)、]”符号好产生一个区间值");
                }
                String[] doubleArr = controlVal.substring(1, controlVal.length() - 1).split(",|，");
                String[] limitArr = null;
                if (!StringUtils.isEmpty(base.getDomain())) {
                    limitArr = base.getDomain().substring(1, base.getDomain().length() - 1).split(",");
                }
                for (String str : doubleArr) {

                    if (limitArr != null && !StringUtils.isEmpty(base.getDomain()) && !validateSectionVal(str, limitArr, base.getDataType())) {
                        throw new IllegalStateException(base.getNameCN() + "的参数值请输入在" + base.getDomain() + "区间的值");
                    }
                }
                String retStr = controlVal.substring(0, 1) + controlVal.substring(1, controlVal.length() - 1) + controlVal.substring(controlVal.length() - 1);
                return retStr;
            }
        } else if (type.equals("out")) {
            if (base.getDataType().equals("String")) {
                if (!StringUtils.isEmpty(base.getDomain())) {
                    Domain domain = getDomain(base.getDomain());
                    for (DomainItem item : domain.getDomainItems()) {
                        if (item.getLabel().equals(controlVal)) {
                            return item.getValue();
                        }
                    }
                } else {
                    values = controlVal;
                    return values;
                }
            } else if (base.getDataType().equals("Double") || base.getDataType().equals("Long")) {
                if (!isNumber(controlVal))
                    throw new IllegalStateException(base.getNameCN() + "的参数值请输入数字");
                if (!StringUtils.isEmpty(base.getDomain())) {
                    String[] limitArr = base.getDomain().substring(1, base.getDomain().length() - 1).split(",");
                    if (!validateSectionVal(controlVal, limitArr, base.getDataType())) {
                        throw new IllegalStateException(base.getNameCN() + "的参数值请输入在" + base.getDomain() + "区间的值");
                    }
                }
                return controlVal;
            } else if (base.getDataType().equals("Date")) {
                if (!DateCheckUtils.dateFormatCheck(controlVal))
                    throw new IllegalStateException(base.getNameCN() + "的参数值请输入日期格式");
                if (!StringUtils.isEmpty(base.getDomain())) {
                    String[] limitArr = base.getDomain().substring(1, base.getDomain().length() - 1).split(",");
                    if (!validateSectionVal(controlVal, limitArr, base.getDataType())) {
                        throw new IllegalStateException(base.getNameCN() + "的参数值请输入在" + base.getDomain() + "区间的值");
                    }
                }
                return controlVal;
            }
        }
        return "";
    }

    /**
     * 解析策略树
     */
    public PolicyTreeModel parsePolicyTree(MultipartFile file, String projectCode,String rankRelationId) throws Exception {
        PolicyTreeModel entity = new PolicyTreeModel();
        Workbook workbook = readExcelData(file, projectCode);
        // 2：动作场景页签(优先获取动作场景，用于保存叶子时获取ID)
        Sheet sheet2 = workbook.getSheetAt(1);
        List<PolicyTreeScene> scenes = getActionSceneList(sheet2);
        entity.setActionScene(scenes);

        // 1：策略树页签
        Sheet sheet = workbook.getSheetAt(0);
        Row row = sheet.getRow(0);
        // 第一行获取树名
        if (row.getCell(0) == null)
            throw new IllegalStateException("请填写决策树模型名称");
        // --1.1：获取策略树(主表)
        RuleManage policyTree = new RuleManage();
        policyTree.setRankRelationId(rankRelationId);
        String[] arr = file.getOriginalFilename().split("_");
        if (arr.length == 3) {
            policyTree.setCode(arr[0]);
            policyTree.setVersion(arr[1]);
        }
        policyTree.setProjectCode(projectCode);
        policyTree.setName(getCellValue(row.getCell(0)));
        entity.setPolicyTreeModel(policyTree);
        // --1.2：获取决策键
        List<PolicyTreeKey> keys = new ArrayList<PolicyTreeKey>();
        getPolicyTreeKeyList(sheet, 1, keys);
        entity.setPolicyTreeKey(keys);
        // --1.3：获取策略树树形
        List<PolicyTreeItem> items = getPolicyTreeItem(sheet, keys, scenes);
        entity.setPolicyTreeItem(items);
        return entity;
    }

    /**
     * 获取策略树树形
     *
     * @param keys   决策键
     * @param scenes 动作场景
     */
    private List<PolicyTreeItem> getPolicyTreeItem(Sheet sheet,
                                                   List<PolicyTreeKey> keys, List<PolicyTreeScene> scenes) throws Exception {
        List<PolicyTreeItem> items = new ArrayList<PolicyTreeItem>();
        // 获取根节点
        Row row = sheet.getRow(1);
        this.getMergedCell(sheet, mergedRegionList, "policyTree");// 合并单元格模式，获取单元格list
        // 第一行获取树名
        if (row.getCell(1) == null)
            throw new IllegalStateException("请填写决策树根节点名称");
        // 根节点
        int keyCount = keys.size();// 决策键的个数
        PolicyTreeItem rootItem = new PolicyTreeItem("ROOT_V", getCellValue(row.getCell(1)), 0);
        rootItem.setFloorNum((keyCount + 1) + "");
        items.add(rootItem);

        // 校验叶子节点值
        row = sheet.getRow(keyCount + 1);// 叶子节点所在行
        int leafNum = row.getPhysicalNumberOfCells() - 1;// 获取叶子节点个数（需扣除最后一个"{#}"）
        // 动作场景map {controlValue, sceneId}
        Map<String, String> sceneMap = new HashMap<String, String>();
        for (PolicyTreeScene scene : scenes) {
            sceneMap.put(scene.getControlValue(), scene.getId());
        }
        checkLeaf(row, leafNum, sceneMap);

        initMergedCellRowAndCol();// 初始化构造合并单元格 首列

        // 树形{row+col,item}
        Map<String, PolicyTreeItem> itemMap = new HashMap<String, PolicyTreeItem>();
        itemMap.put(1 + "-" + 1, rootItem);
        // 动作场景输入变量名称
        String paramName = scenes.get(0).getLabel();
        BomField param = paramZnMap.get(paramName);
        // 决策键map {floor, Key Object}
        Map<Integer, PolicyTreeKey> keyMap = new HashMap<Integer, PolicyTreeKey>();
        for (PolicyTreeKey key : keys) {
            keyMap.put(key.getFloor(), key);
        }
        // 从叶子节点开始循环遍历
        for (int i = 0; i < leafNum; i++) {
            String leafName = getCellValue(sheet.getRow(keyCount + 1).getCell(i + 1));
            PolicyTreeItem leafItem = new PolicyTreeItem(StringUtils.generateShortUuid(), leafName, keyCount);
            leafItem.setIsLeaf("true");
            String controlValue = leafName;
            if ("String".equals(param.getDataType()) && !StringUtils.isEmpty(param.getDomain())) {
                controlValue = convertDomain(param.getDomain(), leafName);
            }
            leafItem.setActionSceneId(sceneMap.get(controlValue));
            // 重新设置名称，例如：男 -> (1)男
            leafItem.setName("(" + (i + 1) + ")" + leafName);
            getPolicyTreeItemList(sheet, leafItem, keyCount + 1, i + 1, keyCount, i + 1, items, itemMap, keyMap);
        }
        markError("0");
        return items;
    }

    /**
     * 校验叶子
     *
     * @param row     叶子所在行
     * @param leafNum 叶子个数
     */
    private void checkLeaf(Row row, int leafNum, Map<String, String> sceneMap) {
        for (int i = 0; i < leafNum; i++) {
            int colIndex = i + 1; // 列
            int rowIndex = row.getRowNum();
            Cell cell = row.getCell(colIndex);
            if (cell == null || StringUtils.isEmpty(getCellValue(cell))) {
                markError("第" + (rowIndex + 1) + "行，第" + (colIndex + 1) + "列为空");
                continue;
            } else {
                // 叶子节点值的校验
                String leafName = getCellValue(cell);
                if (sceneMap.get(leafName) == null) {// 在动作场景中无该输入项
                    markError("第" + (rowIndex + 1) + "行，第" + (colIndex + 1) + "列叶子[" + leafName + "]无对应动作场景");
                    continue;
                }

            }
        }
        markError("0");
    }

    /**
     * 获取决策键列表
     *
     * @param rowIndex 行号
     * @param keyList  决策键列表
     */
    private void getPolicyTreeKeyList(Sheet sheet, int rowIndex, List<PolicyTreeKey> keyList) {
        Cell keyCell = sheet.getRow(rowIndex).getCell(0);
        if (keyCell == null || StringUtils.isEmpty(getCellValue(keyCell))) {
            getPolicyTreeKeyList(sheet, rowIndex + 1, keyList);
        } else {
            String key = getCellValue(keyCell); // 获取当前行决策键
            if ("{end}".equals(key)) {
                return;
            } else if ("决策键".equals(key)) {
                PolicyTreeKey policyTreeKey = new PolicyTreeKey(UUID.randomUUID().toString(), key, null, rowIndex - 1);
                keyList.add(policyTreeKey);
                getPolicyTreeKeyList(sheet, rowIndex + 1, keyList);
            } else {
                BomField param = paramZnMap.get(key);
                if (param == null) {
                    throw new IllegalStateException("第" + (rowIndex + 1) + "行决策键\"" + key + "\"不存在，请确定数据模型中存在此参数。");
                } else {
                    PolicyTreeKey policyTreeKey = new PolicyTreeKey(UUID.randomUUID().toString(), key, param.getName(), rowIndex - 1);
                    policyTreeKey.initKeyModel(param);
                    keyList.add(policyTreeKey);
                    getPolicyTreeKeyList(sheet, rowIndex + 1, keyList);
                }
            }
        }
    }

    // 重写上面的方法，合并单元格模式
    private void getPolicyTreeItemList(Sheet sheet, PolicyTreeItem childItem,
                                       int childRowIndex, int childColIndex, int rowIndex, int colIndex,
                                       List<PolicyTreeItem> itemList, Map<String, PolicyTreeItem> itemMap,
                                       Map<Integer, PolicyTreeKey> keyMap) throws Exception {
        colIndex = getMergeCellRowIndex(rowIndex, colIndex);// 转换该单元格具体位置（解决wps无法从后获取合并单元格下标bug）
        Cell parentCell = sheet.getRow(rowIndex).getCell(colIndex);// 父节点
        String cellVal = getCellValue(parentCell);
        if (StringUtils.isEmpty(cellVal) || "{#}".equals(cellVal)) {// 内容为空，向上查找
            if ((rowIndex - 1) <= 0) {
                throw new IllegalStateException("第" + (childRowIndex + 1) + "行，第" + (childColIndex + 1) + "列节点[" + getCellValue(sheet.getRow(childRowIndex).getCell(childColIndex)) + "]无父节点");
            } else {
                getPolicyTreeItemList(sheet, childItem, childRowIndex, childColIndex, rowIndex - 1, colIndex, itemList, itemMap, keyMap);
            }
        } else {
            String key = rowIndex + "-" + colIndex;// 行+列
            PolicyTreeItem parentItem = null;
            if (itemMap.get(key) != null) {
                parentItem = itemMap.get(key);
            } else {
                parentItem = new PolicyTreeItem(StringUtils.generateShortUuid(), cellVal, rowIndex - 1);
                itemMap.put(key, parentItem);// 将已找到的父节点分支保存供后续直接使用
            }
            childItem.setPid(parentItem.getId());
            if (!itemList.contains(childItem)) {
                if (!"true".equals(childItem.getIsLeaf()) && !"ROOT_V".equals(childItem.getId())) {// 解析分支
                    parseBranchItem(childItem, keyMap, sheet.getRow(childRowIndex).getCell(childColIndex));
                }
                itemList.add(childItem);
            }
            if (parentItem.getFloor() == 0) {
                return;
            } else {
                getPolicyTreeItemList(sheet, parentItem, rowIndex, colIndex, rowIndex - 1, colIndex, itemList, itemMap, keyMap);
            }
        }

    }

    /**
     * 解析策略树分支节点
     *
     * @param keyMap 决策键map {floor, Key Object}
     * @param cell   单元格
     */
    private void parseBranchItem(PolicyTreeItem branchItem, Map<Integer, PolicyTreeKey> keyMap, Cell cell) throws Exception {

        PolicyTreeKey key = keyMap.get(cell.getRowIndex() - 1);
        branchItem.setKeyId(key.getId());// 设置决策键id
        String content = branchItem.getName();// 分支内容
        int startIndex = content.indexOf("{");
        int endIndex = content.indexOf("}");
        // 包含参数表达式
        if (startIndex > -1 && endIndex > -1 && startIndex < endIndex) {
            String dataType = key.getDataType();
            // reference parseNodeExp()
            //验证括号匹配与否
            String expression = content.substring(startIndex + 1, endIndex);
            while (expression.matches("\\([^\\(\\)]*\\)")) {
                expression = expression.replaceAll("\\([^\\(\\)]*\\)", "");
            }
            if (expression.matches("\\(|\\)")) {
                throw new IllegalStateException("节点表达式有误,请检查!");
            }

            Matcher mat = null;
            if ("Date".equals(dataType) || "Long".equals(dataType) || "Double".equals(dataType)) {
                String[] exps = expression.split("&&");
                String branchName = "";
                List<String> controlList = new ArrayList<String>();
                //匹配>,>=,<,<=
                Pattern digitPattern = Pattern.compile("([\\(\\p{Space}]*)"
                        + "([^\\(><=]+)([><=]=?)\\p{Space}*([\\d\\.-]*)"
                        + "([\\)\\p{Space}]*)");
                Pattern datePattern = Pattern.compile("([\\(\\p{Space}]*)"
                        + "([^\\(><=]+)([><=]=?)\\p{Space}*([\\S\\.]*)"
                        + "([\\)\\p{Space}]*)");

                // 获取第一个表达式
                mat = digitPattern.matcher(exps[0]);
                if (!mat.matches()) {
                    mat = datePattern.matcher(exps[0]);
                }
                if (!mat.matches()) {
                    throw new IllegalStateException("第" + (cell.getRowIndex() + 1) + "行，第"
                            + (cell.getColumnIndex() + 1) + "列参数表达式有误");
                }
                String upSelVal = mat.group(3);
                String upIptText = mat.group(4);
                if (">".equals(upSelVal)) {
                    branchName = "(" + upIptText + ",)";
                } else if (">=".equals(upSelVal)) {
                    branchName = "[" + upIptText + ",)";
                } else if ("==".equals(upSelVal)) {
                    branchName = upIptText;
                } else if ("<".equals(upSelVal)) {
                    branchName = "(," + upIptText + ")";
                } else if ("<=".equals(upSelVal)) {
                    branchName = "(," + upIptText + "]";
                } else {
                    throw new IllegalStateException("第" + (cell.getRowIndex() + 1) + "行，第"
                            + (cell.getColumnIndex() + 1) + "列参数表达式" + upSelVal + "有误");
                }
                //controlList.add(upSelVal);
                branchItem.setLeftOpt(upSelVal);
                controlList.add(upIptText);
                // 获取第二个表达式
                if (exps.length == 2) {
                    mat = digitPattern.matcher(exps[1]);
                    if (!mat.matches()) {
                        throw new IllegalStateException("第" + (cell.getRowIndex() + 1) + "行，第"
                                + (cell.getColumnIndex() + 1) + "列参数表达式有误");
                    }
                    String downSelVal = mat.group(3);
                    String downIptText = mat.group(4);
                    if (!StringUtils.isEmpty(upIptText) || !StringUtils.isEmpty(downIptText)) {
                        String upSymbol = "(";
                        if (">=".equals(upSelVal)) {
                            upSymbol = "[";
                        }
                        String downSymbol = ")";
                        if ("<=".equals(downSelVal)) {
                            downSymbol = "]";
                        }
                        branchName = upSymbol + upIptText + "," + downIptText + downSymbol;
                    }
                    //controlList.add(downSelVal);
                    branchItem.setRightOpt(downSelVal);
                    controlList.add(downIptText);
                }
                String[] controlValues = new String[controlList.size()];
                controlList.toArray(controlValues);
                String strContr = Arrays.toString(controlValues);
                if (strContr != null && strContr.length() > 2) {
                    strContr = strContr.substring(strContr.indexOf("[") + 1, strContr.indexOf("]"));
                }
                branchItem.setControlValue(strContr);
                branchItem.setName(branchName);
                branchItem.setSymbol("");

            } else if ("String".equals(dataType)) {
                if (!StringUtils.isEmpty(key.getDomain())) {
                    //匹配in
                    Pattern inPattern = Pattern.compile("([\\(\\p{Space}]*)"
                            + "([^\\(]+)(in)\\p{Space}*(\\([^\\)]+\\))"
                            + "([\\)\\p{Space}]*)");
                    //匹配not in
                    Pattern notInPattern = Pattern.compile("([\\(\\p{Space}]*)"
                            + "([^\\(]+)(not\\p{Space}*in)\\p{Space}*(\\([^\\)]+\\))"
                            + "([\\)\\p{Space}]*)");
                    mat = notInPattern.matcher(expression);
                    if (!mat.matches()) {
                        mat = inPattern.matcher(expression);
                    }
                    if (!mat.matches()) {
                        throw new IllegalStateException("第" + (cell.getRowIndex() + 1) + "行，第"
                                + (cell.getColumnIndex() + 1) + "列参数表达式有误");
                    }
                    String name = mat.group(4).substring(1, mat.group(4).length() - 1);
                    branchItem.setName(name);
                    if (mat.group(3).equals("in")) {
                        branchItem.setSymbol("1");
                    } else if (mat.group(3).startsWith("not")) {
                        branchItem.setSymbol("0");
                    }
                    List<String> controlList = new ArrayList<String>();
                    String[] controls = name.split(",");
                    for (String s : controls) {
                        controlList.add(convertDomain(key.getDomain(), s));
                    }
                    String[] controlValues = new String[controlList.size()];
                    branchItem.setControlValue(Arrays.toString(controlValues));
                } else {
                    //字符类型匹配等于不等于
                    Pattern stringPattern = Pattern.compile("([\\(\\p{Space}]*)"
                            + "([^\\(=!]+)([=!]=?)\\p{Space}*([\\S]+)"
                            + "([\\)\\p{Space}]*)");
                    //匹配startsWith、endsWith、contains
                    Pattern startsWithPattern = Pattern.compile("([\\(\\p{Space}]*)"
                            + "([^\\(]*)(startsWith|endsWith|contains)\\p{Space}*([\\S]+)"
                            + "([\\)\\p{Space}]*)");
                    //匹配not contains
                    Pattern notContainsPattern = Pattern.compile("([\\(\\p{Space}]*)"
                            + "([^\\(]*)(not\\p{Space}*contains)\\p{Space}*([\\S]+)"
                            + "([\\)\\p{Space}]*)");
                    mat = stringPattern.matcher(expression);
                    if (!mat.matches()) {
                        mat = notContainsPattern.matcher(expression);
                    }
                    if (!mat.matches()) {
                        mat = startsWithPattern.matcher(expression);
                    }


                    if (!mat.matches()) {
                        throw new IllegalStateException("第" + (cell.getRowIndex() + 1) + "行，第"
                                + (cell.getColumnIndex() + 1) + "列参数表达式有误");
                    }
                    branchItem.setSymbol(mat.group(3));
                    branchItem.setControlValue(mat.group(4));
                    branchItem.setName(mat.group(4));

                }

            } else {
                // 不包含表达式
                branchItem.setControlValue(content);
                if ("有".equals(content) || "是".equals(content)) {
                    branchItem.setSymbol("1");
                } else if ("无".equals(content) || "否".equals(content)) {
                    branchItem.setSymbol("0");
                }
            }
        }
    }


    // 获取动作场景 reference parseEvaluationIndex
    private List<PolicyTreeScene> getActionSceneList(Sheet sheet) throws Exception {
        List<PolicyTreeScene> actionScene = new ArrayList<PolicyTreeScene>();
        int rowNum = sheet.getLastRowNum();
        Row row = sheet.getRow(0);
        int colNum = row.getPhysicalNumberOfCells();
        PolicyTreeScene temp = null;
        for (int x = 0; x <= rowNum; x++) {// 从第1行开始行循环
            row = sheet.getRow(x);
            colNum = row.getPhysicalNumberOfCells();
            if (row.getCell(0).toString().indexOf("{end}") > -1) {
                break;
            }
            int j = 0;
            if (x == 0) {//正文内容应该从第二行开始,第一行为表头的标题
                if (row.getCell(0) == null || StringUtils.isEmpty(row.getCell(0).toString()))
                    throw new IllegalStateException("请填写动作场景名称");
                continue;
            } else if (x == 1) {// 动作场景标题
                temp = new PolicyTreeScene();
                while (j < colNum) {// 从第1列开始列循环
                    if (row.getCell(j) == null) {
                        throw new IllegalStateException("第" + (x + 1) + "行，第" + (j + 1) +
                                "列的参数名称为空");
                    }
                    if (row.getCell(j).toString().indexOf("{#}") > -1) {
                        break;
                    }
                    BomField param = paramZnMap.get(row.getCell(j).toString());
                    if (param == null) {
                        throw new IllegalStateException("第" + (x + 1) + "行，第" + (j + 1) +
                                "列的参数\"" + param + "\"不存在，请确定数据模型中存在此参数。");
                    }
                    if (j == 0) {// 每行第一列：输入变量
                        temp.initSceneModel(param);
                    } else {
                        PolicyTreeScene child = new PolicyTreeScene();
                        child.setId(StringUtils.generateShortUuid());
                        child.initSceneModel(param);
                        temp.getOutputVariables().add(child);
                    }
                    j++;
                }
            } else {// 具体属性值
                if (temp == null)
                    throw new IllegalStateException("未找到对应的参数信息");
                PolicyTreeScene rowItem = (PolicyTreeScene) temp.deepCopy();
                rowItem.setId(UUID.randomUUID().toString());
                while (j < colNum) {
                    if (row.getCell(j) == null)
                        break;
                    if (row.getCell(j).toString().indexOf("{#}") > -1) {
                        break;
                    }
                    String controlValue = row.getCell((short) j).toString();
                    if (j == 0) {
                        controlValue = validateControlValue(rowItem, controlValue);
                        if (controlValue.length() == 0) {
                            throw new IllegalStateException("第" + (x + 1) + "行，第" + (j + 1) + "列的参数值有误，请确定是否输入了正确的数据类型。");
                        }
                        rowItem.setControlValue(controlValue);
                    } else {
                        PolicyTreeScene child = rowItem.getOutputVariables().get(j - 1);
                        controlValue = validateControlValue(child, controlValue);
                        if (controlValue.length() == 0) {
                            throw new IllegalStateException("第" + (x + 1) + "行，第" + (j + 1) + "列的参数值有误，请确定是否输入了正确的数据类型。");
                        }
                        child.setControlValue(controlValue);
                    }
                    j++;
                }
                actionScene.add(rowItem);
            }
        }
        return actionScene;
    }

    /***根据参数中文名或英文名获取数据模型参数***/
    public BomField getParamByName(String name) {

        if (paramZnMap == null || paramEnMap == null)
            return null;
        //有类名前缀
        if (name.indexOf(".") > -1) {
            return this.parentMap.get(name);
        } else if (this.repeatedName.containsKey(name)) {
            throw new IllegalStateException("参数名称\"" + name + "\"有重复数据,请加上类名前缀!");
        }
        BomField param = paramZnMap.get(name);
        if (param == null) {
            param = paramEnMap.get(name);
        }
        return param;
    }
    
    public Map<String,Symbol> getSymbolMap() {
    	if(symbolMap.isEmpty()) {
	    	List<Symbol> symbolList= SymbolCreator.initmeth();
	
	    	for(Symbol symbol:symbolList) {
	    		symbolMap.put(symbol.getLabel().trim(),symbol);
	    	}
    	}
    	return symbolMap;
    }


    /**
     * 转换domain，从domainKey中获取domain，将convertName转换成label
     */
    private String convertDomain(String domainKey, String convertName) {
        Domain domain = getDomain(domainKey);
        for (DomainItem dom : domain.getDomainItems()) {
            if (dom.getLabel().equals(convertName)) {
                convertName = dom.getValue();
                break;
            }
        }
        return convertName;
    }

    /***根据数据模型的domain值获取数据模型属性***/
    public Domain getDomain(String key) {
        Domain domain = null;
        if (attrMap.containsKey(key))
            domain = attrMap.get(key);
        return domain;
    }

    private void getParam(Map<String, Bom> metaMap) {
        List<Bom> list = BomCreator.findTopObject(metaMap);
        if (list == null || list.size() == 0)
            return;
        for (Bom item : list) {
            if (item.getBomFields() == null || item.getBomFields().size() == 0)
                continue;
            for (BomField field : item.getBomFields()) {
                field.setClassName(item.getName());
                //判断是否存在重复参数名称,有则记录到Map对象中
                if (this.paramZnMap.containsKey(field.getLabel())) {
                    this.repeatedName.put(field.getLabel(), "0");
                }
                this.paramZnMap.put(field.getLabel(), field);
                this.paramEnMap.put(field.getName(), field);
                this.parentMap.put(item.getLabel() + "." + field.getLabel(), field);
            }
        }
        //{treeId:"3-1",className:"InitialScore",nameCN:"初始评分",nameEN:"initialScore",dataType:"Double",contentType:"scoreDetail",scoreParam:"0"};
        BomField initial = new BomField();
        initial.setClassName("InitialScore");
        initial.setLabel("初始评分");
        initial.setName("initialScore");
        initial.setDataType("Double");
        this.paramZnMap.put("初始评分", initial);
    }

    private boolean isNumber(String number) {
        Pattern pattern = Pattern.compile("^(-?\\d+)(\\.\\d+)?$");
        return pattern.matcher(number).matches();
    }

    private boolean validateSectionVal(String controlVal, String[] limitArr, String dataType) {
        //TODO 日期校验
        if ("Date".equalsIgnoreCase(dataType)) {
            for (int j = 0; j < limitArr.length; j++) {
                if (j == 0 && !StringUtils.isEmpty(limitArr[j]) && controlVal.compareTo(limitArr[j]) < 0) {
                    return false;
                }
                if (j == 1 && !StringUtils.isEmpty(limitArr[j]) && controlVal.compareTo(limitArr[j]) > 0) {
                    return false;
                }
            }
        } else {
            // controlVal =StringUtils.replace(controlVal, "-", "");
            float v = Float.parseFloat(controlVal);
            for (int i = 0; i < limitArr.length; i++) {
                // limitArr[i] = StringUtils.replace(limitArr[i], "-", "");
                if (i == 0 && !StringUtils.isEmpty(limitArr[i]) && v < Float.parseFloat(limitArr[i])) {
                    return false;
                }
                if (i == 1 && !StringUtils.isEmpty(limitArr[i]) && v > Float.parseFloat(limitArr[i])) {
                    return false;
                }
            }
        }
        return true;
    }

    private <T> List<T> copyList(List<T> list) throws Exception {
        List<T> newList = new ArrayList<T>();
        for (T item : list) {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(item);
            // 将流序列化成对象
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            T newItem = (T) ois.readObject();
            newList.add(newItem);
        }
        return newList;
    }

    /**
     * 合并单元格处理--加入list
     *
     * @mergeType 合并类型，如果是决策树只能向下合并
     */
    public void getMergedCell(Sheet sheet, List<CellRangeAddress> list, String mergeType) {
        // 获得一个 sheet 中合并单元格的数量
        int sheetmergerCount = sheet.getNumMergedRegions();
        // 遍历合并单元格
        for (int i = 0; i < sheetmergerCount; i++) {
            // 获得合并单元格加入list中
            CellRangeAddress ca = sheet.getMergedRegion(i);
            if ("decisionTree".equals(mergeType)) {
                if (ca.getFirstRow() > 2 && ca.getFirstColumn() != ca.getLastColumn()) {
                    throw new IllegalStateException("决策树节点的单元格只能向下合并列");
                }
            } else if ("policyTree".equals(mergeType)) {
                if (ca.getFirstRow() != ca.getLastRow()) {
                    throw new IllegalStateException("策略树节点的单元格只能横向合并列");
                }
            }
            list.add(ca);
        }
    }

    /**
     * 判断单元格是否为合并单元格
     *
     * @param cell  需要判断的单元格
     */
    public CellRangeAddress isMergedCell(Cell cell) {
        int firstC = 0;
        int lastC = 0;
        int firstR = 0;
        int lastR = 0;
        for (CellRangeAddress ca : mergedRegionList) {
            // 获得合并单元格的起始行, 结束行, 起始列, 结束列
            firstC = ca.getFirstColumn();
            lastC = ca.getLastColumn();
            firstR = ca.getFirstRow();
            lastR = ca.getLastRow();
            if (cell.getColumnIndex() <= lastC && cell.getColumnIndex() >= firstC) {
                if (cell.getRowIndex() <= lastR && cell.getRowIndex() >= firstR) {
                    return ca;
                }
            }
        }
        return null;
    }

    /**
     * 构造合并单元格 首列 Map<2,,Map<4,3>> 2：某行；3：合并单元格列首列；4：合并单元格中的某列
     */
    private void initMergedCellRowAndCol() {
        int rowIndex = 0;// 合并单元格 行
        int firstColIndex = 0;// 合并单元格 起始列
        int lastColIndex = 0;// 合并单元格 结束列
        for (CellRangeAddress ca : mergedRegionList) {
            rowIndex = ca.getFirstRow();
            firstColIndex = ca.getFirstColumn();
            lastColIndex = ca.getLastColumn();
            int tempColIndex = firstColIndex;
            while (tempColIndex <= lastColIndex) {
                Map<Integer, Integer> colIndexMap = null;
                if (mergeCellMap.get(rowIndex) != null) {
                    colIndexMap = mergeCellMap.get(rowIndex);
                } else {
                    colIndexMap = new HashMap<Integer, Integer>();
                }
                colIndexMap.put(tempColIndex, firstColIndex);
                mergeCellMap.put(rowIndex, colIndexMap);
                tempColIndex++;
            }
        }
    }

    /**
     * 通过某列获取相对应的合并单元格首列
     *
     * @param rowIndex 行
     * @param colIndex 列
     */
    private int getMergeCellRowIndex(int rowIndex, int colIndex) {
        int mergeRowIndex = colIndex;
        // 获取某行所有的单元格
        Map<Integer, Integer> rowIndexMap = mergeCellMap.get(rowIndex);
        if (rowIndexMap != null) {
            // 获取某列的首列
            Integer tempColIndex = rowIndexMap.get(colIndex);
            if (tempColIndex != null) {
                mergeRowIndex = tempColIndex;
            }
        }
        return mergeRowIndex;
    }

    /**
     * 获取单元格的值
     */
    private String getCellValue(Cell cell) {
        if (cell == null) return "";
        if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
            return cell.getStringCellValue();
        } else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
            return String.valueOf(cell.getBooleanCellValue());
        } else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
            return cell.getCellFormula();
        } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
            return String.valueOf(cell.getNumericCellValue());
        }
        return "";
    }

    /**
     * 删除目录（文件夹）以及目录下的文件
     *
     * @param sPath 被删除目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String sPath) {
        //如果sPath不以文件分隔符结尾，自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                files[i].delete();
            } //删除子目录
            else {
                deleteDirectory(files[i].getAbsolutePath());
            }
        }
        //删除当前目录
        return dirFile.delete();
    }

    /**
     * 累积记录错误
     */
    private void markError(String msg) {
        if (this.errCount >= 5) {
            throw new IllegalStateException(this.errMsg.toString());
        }
        if ("0".equals(msg)) {
            if (this.errCount > 0) {
                throw new IllegalStateException(this.errMsg.toString());
            }
        } else if (!StringUtils.isEmpty(msg)) {
            this.errCount++;
            this.errMsg.append(msg).append("\n");
            if (this.errCount >= 5) {
                throw new IllegalStateException(this.errMsg.toString());
            }
        }

    }

    public Map<String, BomField> getParamZnMap() {
        return this.paramZnMap;
    }

    /**
     * 解析上传的决策树文件
     */
    public DecisionTreeEntity parseDecisionTree(MultipartFile file, String projectCode, String rankRelationId) throws Exception {
        DecisionTreeEntity treeEntity = new DecisionTreeEntity();
        RuleManage tree = new RuleManage();
        tree.setRankRelationId(rankRelationId);
        String[] arr = file.getOriginalFilename().split("_");
        if (arr.length == 3) {
            tree.setCode(arr[0]);
            tree.setVersion(arr[1]);
        }
        DecisionSubNode subNode = new DecisionSubNode();
        subNode.setResultItems(new ArrayList<DecisionSubNodeItem>());
        nodeList = new ArrayList<DecisionSubNode>();
        outVarList = new ArrayList<BomField>();
        Workbook workbook = readExcelData(file, projectCode);
        Sheet sheet = workbook.getSheetAt(0);
        Row row = sheet.getRow(0);

        //1.第一行获取树名
        if (row.getCell(0) == null)
            throw new IllegalStateException("请填写决策树模型名称");
        tree.setName(row.getCell(0).toString());
        if (row.getCell(0).toString().indexOf("@@") > -1) {
            String[] nameArr = row.getCell(0).toString().split("@@");
            tree.setName(nameArr[0]);
            if ("0".equals(nameArr[1]) || "1".equals(nameArr[1])) {
                tree.setIsSingle(nameArr[1]);
            } else {
                tree.setIsSingle("1");
            }
        }
        tree.setProjectCode(projectCode);
        //2.第二行获取输出变量 参数
        row = sheet.getRow(2);
        int colNum = row.getPhysicalNumberOfCells();
        for (int i = 0; i < colNum; i++) {
            if (row.getCell(i) == null ||
                    StringUtils.isEmpty(row.getCell(i).toString())) {
                markError("第" + 3 + "行，第" + (i + 1) + "列为空");
                continue;
            }
            //变量名称列开始
            String str = row.getCell(i).toString();
            if (str.indexOf("{#}") > -1) {//列结束标志
                this.outColIndex = ++i;
                str = row.getCell(i).toString();
                while (i < colNum && str.indexOf("{#}") == -1) {
                    BomField param = paramZnMap.get(str);
                    if (param == null) {
                        markError("第" + 3 + "行，第" + (i + 1) + "列的参数\"" +
                                str + "\"不存在，请确定数据模型中存在此参数。");
                        continue;

                    }
                    outVarList.add(param);
                    DecisionSubNodeItem item = new DecisionSubNodeItem();
                    item.initModel(param);
                    subNode.getResultItems().add(item);
                    i++;
                    str = row.getCell(i).toString();
                }
            }
        }
        markError("0");

        //3.解析节点内容,从根结点开始
        row = sheet.getRow(3);
        this.getMergedCell(sheet, mergedRegionList, "decisionTree");
        Cell rootCell = row.getCell(0);
        DecisionSubNode rootNode = parseTreeNode(rootCell, null);
        CellRangeAddress mergedCell = this.isMergedCell(rootCell);
        if (mergedCell == null) {
            recursiveChildNode(rootNode, sheet, row.getCell(1), 0);
        } else {
            recursiveChildNode(rootNode, sheet, row.getCell(1), mergedCell.getNumberOfCells() - 1);
        }
        markError("0");
        treeEntity.setRuleManage(tree);
        treeEntity.setNodeList(nodeList);
        for (int i = 0; i < this.nodeList.size(); i++) {
            DecisionSubNode node = nodeList.get(i);
            if (StringUtils.isEmpty(node.getPid())) {
                throw new Exception(node.getName() + "节点的父节点ID为空");
            }
            if (StringUtils.isEmpty(node.getId())) {
                node.setId(com.tansun.rule.utils.StringUtils.generateShortUuid());
            }
            node.setType("open");
            node.setNum(i);
        }
        //treeEntity.setDecisionTreefoList(outInfoList);
        return treeEntity;
    }

    public ExclusionsVo parseExclusion(MultipartFile file, String projectCode) throws Exception {
        ExclusionsVo exclusionsVo = new ExclusionsVo();
        List<ExclusionsBO> exclusionsList = new ArrayList<ExclusionsBO>();

        RuleManage exclusionsModel = new RuleManage();

        String[] arr = file.getOriginalFilename().split("_");
        if (arr.length == 3) {
            exclusionsModel.setCode(arr[0]);
            exclusionsModel.setVersion(arr[1]);
        }
        exclusionsModel.setProjectCode(projectCode);
        // try
        Workbook workbook = readExcelData(file);
        Sheet sheet = workbook.getSheetAt(0);

        // 输出变量列表
        List<BomField> outputVars = new ArrayList<BomField>();

        int rowCount = sheet.getLastRowNum(); // 从 0 行开始
        int cellCount = 0;
        for (int i = 0; i <= rowCount; i++) {
            Row row = sheet.getRow(i);
            // 列数
            cellCount = row.getPhysicalNumberOfCells();

            Cell endCell = row.getCell(0);
            // 读取到最后一行，文件解析完毕
            if (endCell != null && endCell.toString().indexOf("{end}") > -1) {
                break;
            }

            if (i == 0) { // 标题行
                String title = row.getCell(0).toString();
                if (StringUtils.isEmpty(title)) {
                    throw new BizException("表格第 " + (i + 1) + " 行，请填写排除项模型名称");
                }

                exclusionsModel.setName(title);
            } else if (i == 1) { // 表格头变量名
                for (int j = 2; j < cellCount; j++) { // 从第3列开始
                    Cell cell = row.getCell(j);
                    String value = null;
                    if (cell == null || "".equals(value = cell.toString())) { // StringUtils.isEmpty
                        throw new BizException("表格第 " + (i + 1) + " 行第 " + (j + 1) + " 列，请填写正确的变量名");
                    } else if (value.indexOf("{#}") > -1) {
                        break;
                    }

                    BomField outputVar = getParamZnMap().get(value);
                    if (outputVar == null) {
                        throw new BizException("表格第 " + (i + 1) + " 行第 " + (j + 1) +
                                " 列模型\"" + value + "\"不存在，请检查数据模型");
                    }
                    outputVars.add(outputVar);
                }
            } else { // 值列表
                // 排除项元素
                ExclusionsBO valueItem = new ExclusionsBO();
                valueItem.setColumnNo(0);
                valueItem.setRowNo(i);
                // 输出变量值列表
                List<ExclusionsBO> outputList = new ArrayList<ExclusionsBO>();

                for (int k = 0; k < cellCount; k++) {
                    Cell cell = row.getCell(k);
                    String value = null;
                    if (cell == null || "".equals(value = cell.toString())) { // StringUtils.isEmpty
                        throw new BizException("表格第 " + (i + 1) + " 行第 " + (k + 1) + " 列，请填写正确的值");
                    } else if (value.indexOf("{#}") > -1) { // 结束
                        break;
                    }

                    if (k == 0) { // 输入变量名
                        BomField inputVar = getParamZnMap().get(value);
                        if (inputVar == null) {
                            throw new BizException("表格第 " + (i + 1) + " 行第 " + (k + 1) +
                                    " 列模型\"" + value + "\"不存在，请检查数据模型");
                        }
                        valueItem.initModel(inputVar);
                    } else if (k == 1) { // 输入变量值
                        BaseItem v = new BaseItem(valueItem);
                        String controlValue = validateValue(v, value, "in", false);
                        if ("Date".equals(v.getDataType()) || "Long".equals(v.getDataType()) || "Double".equals(v.getDataType())) {
                            valueItem.setLowerOpt(controlValue.substring(0, 1));
                            valueItem.setControlValue(controlValue.substring(1, controlValue.length() - 1));
                            valueItem.setUpperOpt(controlValue.substring(controlValue.length() - 1));
                        } else
                            valueItem.setControlValue(controlValue);
                        if (StringUtils.isEmpty(controlValue)) {
                            throw new BizException("表格第 " + (i + 1) + " 行第 " + (k + 1) + " 列，请填写正确的输入变量值");
                        }

                    } else { // 输出变量值
                        ExclusionsBO outputItem = new ExclusionsBO();
                        outputItem.initModel(outputVars.get(k - 2));
                        outputItem.setColumnNo(k + 1);
                        outputItem.setRowNo(i);
                        BaseItem v = new BaseItem(outputItem);
                        String controlValue = validateValue(v, value, "out", false);
                        if (StringUtils.isEmpty(controlValue)) {
                            throw new BizException("表格第 " + (i + 1) + " 行第 " + (k + 1) + " 列，请填写正确的输出变量值");
                        }
                        outputItem.setControlValue(controlValue);

                        outputList.add(outputItem);
                    }
                }

                valueItem.setList(outputList);
                exclusionsList.add(valueItem);
            }
        }

        exclusionsVo.setExclusionsModel(exclusionsModel);
        exclusionsVo.setExclusionsList(exclusionsList);
        return exclusionsVo;
    }

    public Workbook readExcelData(MultipartFile file, String projectCode) throws Exception {
        Workbook workbook = null;
        try {
            if (file.getOriginalFilename().toLowerCase().endsWith("xlsx")) {
                workbook = new XSSFWorkbook(file.getInputStream());
            } else if (file.getOriginalFilename().toLowerCase().endsWith("xls")) {
                workbook = new HSSFWorkbook(file.getInputStream());
            } else {
                throw new IllegalStateException("文件格式有误");
            }
        } catch (IOException e) {
            LoggerManager.error(e.getMessage(), e, this.getClass());
        } finally {
            if (file != null && file.getInputStream() != null)
                file.getInputStream().close();
        }
        return workbook;
    }

    /**
     * 解析决策树节点内容
     */
    private DecisionSubNode parseTreeNode(Cell cell, DecisionSubNode parentNode) {
        if (cell == null || StringUtils.isEmpty(cell.toString())) {
            throw new IllegalStateException("第" + (cell.getRowIndex() + 1) + "行,第" +
                    (cell.getColumnIndex() + 1) + "列内容为空");
        }
        String content = cell.toString();
        DecisionSubNode subNode = new DecisionSubNode();
        List<DecisionSubNodeItem> nodeItems = new ArrayList<DecisionSubNodeItem>();
        //subNode.setNodeItems(nodeItems);
        if (parentNode != null) {
            subNode.setPid(parentNode.getId());
            subNode.setId(IdGen.uuid());
        } else {
            //无父节点时，则为根节点
            subNode.setId("ROOT_V");
            subNode.setPid("0");
        }

        int startIndex = content.indexOf("{");
        int endIndex = content.indexOf("}");
        //包含参数表达式
        if (startIndex > -1 && endIndex > -1 && startIndex < endIndex) {
            String expression = content.substring(startIndex + 1, endIndex);
            subNode.setName(content.substring(0, startIndex));
            nodeItems = this.parseNodeExp(expression, cell);
            for (DecisionSubNodeItem nodeItem : nodeItems) {

                String name = nodeItem.getNameCN().trim();
                String controlVal = nodeItem.getControlValue();
                BomField param = getParamByName(name);

                if (param == null) {
                    throw new IllegalStateException(
                            "第" + (cell.getRowIndex() + 1) + "行，第"
                                    + (cell.getColumnIndex() + 1) + "列的参数\"" +
                                    name + "\"不存在，请确定数据模型中存在此参数。");
                }
                nodeItem.initModel(param);
                if ("in".equals(nodeItem.getSymbol())) {
                    nodeItem.setSymbol("1");
                } else if ("not in".equals(nodeItem.getSymbol())) {
                    nodeItem.setSymbol("0");
                }
                nodeItem.setControlValue(validateValue(nodeItem, controlVal, "in", true));

            }
        } else {
            //不包含表达式
            if (subNode.getPid() != null && subNode.getPid().equals("0")) {
                subNode.setName("ROOT_V");
                subNode.setType("open");
                subNode.setNum(0);
            } else
                subNode.setName(content);
            subNode.setNodeItems(nodeItems);
        }
        subNode.setNodeItems(nodeItems);
        this.nodeList.add(subNode);
        return subNode;
    }

    private List<DecisionSubNodeItem> parseNodeExp(String content, Cell cell) {
        List<DecisionSubNodeItem> nodeItems = new ArrayList<DecisionSubNodeItem>();
        //验证括号匹配与否
        String exp = content;
        while (exp.matches("\\([^\\(\\)]*\\)")) {
            exp = exp.replaceAll("\\([^\\(\\)]*\\)", "");
        }
        if (exp.matches("\\(|\\)")) {
            throw new IllegalStateException("节点表达式有误,请检查!");
        }
        //先按AND拆分
        String[] expArr = content.split("and");
        //数值型匹配>,>=,<,<=
        Pattern digitPattern = Pattern.compile("([\\(\\p{Space}]*)"
                + "([^\\(><=!]+)([><=!]=?)\\p{Space}*([\\d\\.]+)"
                + "([\\)\\p{Space}]*)");
        //日期类型匹配>,>=,<,<=
        Pattern datePattern = Pattern.compile("([\\(\\p{Space}]*)"
                + "([^\\(><=]+)([><=]=?)\\p{Space}*([\\S]+)"
                + "([\\)\\p{Space}]*)");
        //字符类型匹配等于不等于
        Pattern stringPattern = Pattern.compile("([\\(\\p{Space}]*)"
                + "([^\\(]+)(==|!=)\\p{Space}*([\\S]+)"
                + "([\\)\\p{Space}]*)");
        //匹配in
        Pattern inPattern = Pattern.compile("([\\(\\p{Space}]*)"
                + "([^\\(]+)(in)\\p{Space}*([\\S]+)"
                + "([\\)\\p{Space}]*)");
        //匹配not in
        Pattern notInPattern = Pattern.compile("([\\(\\p{Space}]*)"
                + "([^\\(]+)(not\\p{Space}*in)\\p{Space}*([\\S]+)"
                + "([\\)\\p{Space}]*)");
        //匹配startsWith、endsWith、contains
        Pattern startsWithPattern = Pattern.compile("([\\(\\p{Space}]*)"
                + "([^\\(]+)(startsWith|endsWith|contains)\\p{Space}*([\\S]+)"
                + "([\\)\\p{Space}]*)");
        //匹配not contains
        Pattern notContainsPattern = Pattern.compile("([\\(\\p{Space}]*)"
                + "([^\\(]+)(not\\p{Space}*contains)\\p{Space}*([\\S]+)"
                + "([\\)\\p{Space}]*)");

        DecisionSubNodeItem nodeItem = null;
        for (int i = 0; i < expArr.length; i++) {
            int j = 0;
            String str = expArr[i];
            if (str.indexOf("or") > -1) {
                String[] ary = str.split("or");
                for (j = 0; j < ary.length; j++) {
                    String sub = ary[j];
                    nodeItem = new DecisionSubNodeItem();
                    Matcher mat = digitPattern.matcher(sub);
                    if (!mat.matches()) {
                        mat = stringPattern.matcher(sub);
                    }
                    if (!mat.matches()) {
                        mat = datePattern.matcher(sub);
                    }
                    if (!mat.matches()) {
                        mat = notInPattern.matcher(sub);
                    }
                    if (!mat.matches()) {
                        mat = inPattern.matcher(sub);
                    }
                    if (!mat.matches()) {
                        mat = notContainsPattern.matcher(sub);
                    }
                    if (!mat.matches()) {
                        mat = startsWithPattern.matcher(sub);
                    }

                    if (!mat.matches()) {
                        throw new IllegalStateException("第" + (cell.getRowIndex() + 1) + "行，第"
                                + (cell.getColumnIndex() + 1) + "列参数表达式有误");
                    }
                    if (i > 0 && j == 0) {
                        nodeItem.setLeftOpt("and" + mat.group(1));
                    } else {
                        nodeItem.setLeftOpt(j == 0 ? mat.group(1) : "or" + mat.group(1));
                    }
                    nodeItem.setNameCN(mat.group(2));
                    nodeItem.setSymbol(mat.group(3));
                    nodeItem.setControlValue(mat.group(4));
                    nodeItem.setRightOpt(mat.group(5));
                    nodeItems.add(nodeItem);
                }
            } else {
                nodeItem = new DecisionSubNodeItem();
                Matcher mat = digitPattern.matcher(str);
                if (!mat.matches()) {
                    mat = stringPattern.matcher(str);
                }
                if (!mat.matches()) {
                    mat = datePattern.matcher(str);
                }
                if (!mat.matches()) {
                    mat = notInPattern.matcher(str);
                }
                if (!mat.matches()) {
                    mat = inPattern.matcher(str);
                }
                if (!mat.matches()) {
                    mat = notContainsPattern.matcher(str);
                }
                if (!mat.matches()) {
                    mat = startsWithPattern.matcher(str);
                }


                if (!mat.matches()) {
                    throw new IllegalStateException("第" + (cell.getRowIndex() + 1) + "行，第"
                            + (cell.getColumnIndex() + 1) + "列参数表达式有误");
                }
                nodeItem.setLeftOpt(i == 0 ? mat.group(1) : "and" + mat.group(1));
                nodeItem.setNameCN(mat.group(2));
                nodeItem.setSymbol(mat.group(3));
                nodeItem.setControlValue(mat.group(4));
                nodeItem.setRightOpt(mat.group(5));
                nodeItems.add(nodeItem);
            }
        }
        return nodeItems;
    }

    /**
     * 递归遍历子节点
     *
     * @param num 父节点合并的单元格数量
     */
    private void recursiveChildNode(DecisionSubNode parentNode, Sheet sheet, Cell childCell, int num) {
        markError(null);
        //行结束，读取输出变量
        if (childCell.toString().trim().startsWith("{#}")) {
            boolean isLeaf = false;
            List<DecisionSubNodeItem> resultItems = new ArrayList<DecisionSubNodeItem>();
            for (int i = 0; i < outVarList.size(); i++) {
                BomField bom = outVarList.get(i);
                DecisionSubNodeItem result = new DecisionSubNodeItem();
                result.initModel(bom);
                //DecisionTreeItem outVal = new DecisionTreeItem();
                Cell outCell = sheet.getRow(childCell.getRowIndex()).
                        getCell(this.outColIndex + i);
                if (outCell == null || StringUtils.isEmpty(outCell.toString().trim())) {
                    result.setDisabled("true");
                } else {
                    isLeaf = true;
                    result.setControlValue(validateValue(result, outCell.toString().trim(), "out", true));
                }
                resultItems.add(result);
            }
            if (isLeaf) {
                DecisionSubNode subNode = new DecisionSubNode();
                subNode.setPid(parentNode.getId());
                subNode.setId(IdGen.uuid());
                subNode.setIsLeaf("true");
                subNode.setResultItems(resultItems);
                Cell cell = sheet.getRow(childCell.getRowIndex()).
                        getCell(this.outColIndex - 1);
                String name = "";
                if (cell != null && cell.toString().trim().startsWith("{#}")) {
                    name = cell.toString().trim().substring(3);
                }
                subNode.setName(name);
                this.nodeList.add(subNode);
            }
            return;
        }
        //解析兄弟节点
        for (int i = -1; i < num; i++) {
            //兄弟节点
            Cell siblingsCell = sheet.getRow(childCell.getRowIndex() + 1 + i).getCell(childCell.getColumnIndex());
            if (siblingsCell == null) continue;
            CellRangeAddress mergedCell = this.isMergedCell(siblingsCell);
            try {
                //如果是合并单元格，
                if (mergedCell != null) {
                    //并且是合并单元格里的第一个单元格
                    if (mergedCell.getFirstRow() == siblingsCell.getRowIndex()) {
                        DecisionSubNode childNode = parseTreeNode(siblingsCell, parentNode);
                        Cell nextCell = sheet.getRow(childCell.getRowIndex() + 1 + i).getCell(childCell.getColumnIndex() + 1);
                        recursiveChildNode(childNode, sheet, nextCell, mergedCell.getNumberOfCells() - 1);
                    } else {
                        continue;
                    }
                } else {
                    DecisionSubNode childNode = parseTreeNode(siblingsCell, parentNode);
                    Cell nextCell = sheet.getRow(childCell.getRowIndex() + 1 + i).getCell(childCell.getColumnIndex() + 1);
                    recursiveChildNode(childNode, sheet, nextCell, 0);
                }
            } catch (IllegalStateException e) {
                e.printStackTrace();
                markError(e.getMessage());
            }
        }
        markError(null);
    }
    public static void main(String[] args) {
		System.out.println(isNumeric("10.0"));
	}
}
